package com.imis.module.system.service.impl;

import cn.hutool.core.util.StrUtil;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.imis.base.constant.CommonConstant;
import com.imis.base.constant.DataBaseConstant;
import com.imis.base.util.PasswordUtil;
import com.imis.module.api.model.ro.UserRegisterDTO;
import com.imis.module.base.impl.BaseServiceImpl;
import com.imis.module.system.dao.SysRoleMapper;
import com.imis.module.system.dao.SysUserMapper;
import com.imis.module.system.dao.SysUserRoleMapper;
import com.imis.module.system.model.converter.SysRoleConverter;
import com.imis.module.system.model.converter.SysUserConverter;
import com.imis.module.system.model.po.SysMenu;
import com.imis.module.system.model.po.SysUser;
import com.imis.module.system.model.po.SysUserRole;
import com.imis.module.system.model.ro.PagingQueryUserDTO;
import com.imis.module.system.model.ro.SysGrantRolesToUserRO;
import com.imis.module.system.model.vo.SysUserVO;
import com.imis.module.system.service.ISysUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * <p>
 * 系统用户表 服务实现类
 * </p>
 *
 * @author XinLau
 * @since 2020-03-12
 */
@Service
@Slf4j
@DS(DataBaseConstant.DATA_SOURCE_MASTER)
public class SysUserServiceImpl extends BaseServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    /**
     * 系统角色表-权限组 Mapper 接口
     */
    private SysRoleMapper sysRoleMapper;

    @Autowired(required = false)
    public void setSysRoleMapper(SysRoleMapper sysRoleMapper) {
        this.sysRoleMapper = sysRoleMapper;
    }

    /**
     * 用户角色关联表-菜单权限组 Mapper 接口
     */
    private SysUserRoleMapper sysUserRoleMapper;

    @Autowired(required = false)
    public void setSysUserRoleMapper(SysUserRoleMapper sysUserRoleMapper) {
        this.sysUserRoleMapper = sysUserRoleMapper;
    }

    /**
     * 重复注册验证
     *
     * @param register - 用户信息注册对象
     * @return List<SysUser> - 用户信息
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/12 17:25
     */
    @Override
    public List<SysUser> duplicateRegistrationVerification(final UserRegisterDTO register) {
        return mapper.duplicateRegistrationVerification(register);
    }

    /**
     * 分页查询用户信息
     *
     * @param pagingQueryUserDTO - 用户信息查询对象
     * @return Page<SysUserEntity> - 用户信息
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/12 17:25
     */
    @Override
    public Page<SysUserVO> pagingQuerySysUserListByParameter(final PagingQueryUserDTO pagingQueryUserDTO) {
        // 1.页码、页长
        Page<SysUser> sysUserPage = new Page<>(pagingQueryUserDTO.getPageNumber(), pagingQueryUserDTO.getPageSize());
        // 2.排序字段
        sysUserPage.addOrder(OrderItem.descs(DataBaseConstant.CREATE_TIME_FIELD, DataBaseConstant.UPDATE_TIME_FIELD));
        // 3.条件分页查询
        sysUserPage = mapper.pagingQuerySysUserListByParameter(sysUserPage, pagingQueryUserDTO);
        // 4.PO分页对象转VO实体分页对象
        return SysUserConverter.INSTANCE.getReturnValue(sysUserPage);
    }

    /**
     * 通过用户账号查询用户信息
     *
     * @param username - 用户账号
     * @return SysUser - 用户信息
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/6 16:13
     */
    @Override
    public SysUser queryUserByName(final String username) {
        return mapper.queryUserByName(username);
    }

    /**
     * 创建用户信息
     *
     * @param sysUser - 用户信息
     * @return SysUser - 用户信息
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/6 16:13
     */
    @Override
    public Boolean saveUser(final SysUser sysUser) {
        // 是否用户已被冻结 1(解冻)正常 2冻结
        sysUser.setStatus(CommonConstant.USER_UNFREEZE);
        // 取盐
        sysUser.setSalt(PasswordUtil.getStringSalt());
        // 加密
        sysUser.setPassword(PasswordUtil.encrypt(sysUser.getUsername(), sysUser.getPassword(), sysUser.getSalt()));
        int count = mapper.insert(sysUser);
        return count > 0;
    }

    /**
     * 冻结用户
     *
     * @param identification - 用户唯一标识
     * @return Boolean
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/5 17:25
     */
    @Override
    public Boolean freezeUserByIdentification(final Long identification) {
        // 影响的的行数
        int change = mapper.changeUserStatusByIdentification(CommonConstant.USER_FREEZE, identification);
        return change > 0;
    }

    /**
     * 解冻用户
     *
     * @param identification - 用户唯一标识
     * @return Boolean
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/5 17:25
     */
    @Override
    public Boolean unFreezeUserByIdentification(final Long identification) {
        // 影响的的行数
        int change = mapper.changeUserStatusByIdentification(CommonConstant.USER_UNFREEZE, identification);
        return change > 0;
    }

    /**
     * 用户授权角色
     *
     * @param sysGrantUserToRole - 用户授权角色
     * @return Boolean -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/19 11:10
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
//    @HashCacheEvict(hashIdentification = CacheConstant.PREFIX_SYS_USER_ROLE, hashKey = "'USER_ID_' + #sysGrantUserToRoleRO.userId")
    public Boolean grantRoleToUser(final SysGrantRolesToUserRO sysGrantUserToRole) {
        try {
            // 1.清除之前的授权
            Long userId = sysGrantUserToRole.getUserId();
            // 影响的的行数
            int delete = sysUserRoleMapper.deleteGrantByUserId(userId);
            // 对象转换
            List<SysUserRole> sysUserRoleList = SysRoleConverter.INSTANCE.sysGrantUserToRolesRo2SysUserRoles(sysGrantUserToRole);
            // 2.授权处理
            int grant = sysUserRoleMapper.grantRoleToUser(sysUserRoleList);
            return Boolean.TRUE;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Boolean.FALSE;
        }
    }

    /**
     * 撤销用户角色授权
     *
     * @param userId - 用户编号
     * @return Boolean -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/20 14:22
     */
    @Override
//    @HashCacheEvict(hashIdentification = CacheConstant.PREFIX_SYS_USER_ROLE, hashKey = "'USER_ID_' + #userId")
    public Boolean terminateAllRoleToUser(final Long userId) {
        try {
            // 影响的的行数
            int delete = sysUserRoleMapper.deleteGrantByUserId(userId);
            return delete > 0;
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Boolean.FALSE;
        }
    }

    /**
     * 通过用户编号获取用户角色集合
     *
     * @param userId - 用户编号
     * @return Set<String> - 用户角色集合
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/12 17:25
     */
    @Override
    public Set<String> queryUserRolesSetByUserId(final Long userId) {
        // 获取用户拥有的角色ID集合
        List<Long> roleIdList = sysRoleMapper.selectSysRoleIdArrayByUserId(userId);
        assert roleIdList.size() > 0;
        List<String> arrayList = new ArrayList<>();
        for (Long roleId : roleIdList) {
            arrayList.add(roleId.toString());
        }
        log.debug("-------通过数据库读取用户拥有的角色Rules------username： {}, Roles size: {}", userId, (arrayList == null ? 0 : arrayList.size()));
        return new HashSet<>(arrayList);
    }

    /**
     * 根据用户编号获取权限集合
     *
     * @param userId - 编号
     * @return Set<String> - 权限集合
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/16 09:30
     */
    @Override
    public Set<String> queryUserPermissionsSetByUserId(final Long userId) {
        Set<String> permissionSet = new HashSet<>();
        // 1.获取用户拥有的角色ID集合
        List<Long> roleIdList = sysRoleMapper.selectSysRoleIdArrayByUserId(userId);
        if (roleIdList.size() > 0) {
            // 集合转数组
            List<SysMenu> permissionList = mapper.queryPermissionListByRoleIdArray(roleIdList);
            if (permissionList.size() > 0) {
                for (SysMenu sysMenu : permissionList) {
                    if (StrUtil.isNotEmpty(sysMenu.getPerms())) {
                        permissionSet.add(sysMenu.getPerms());
                    }
                    if (StrUtil.isNotEmpty(sysMenu.getUrl())) {
                        permissionSet.add(sysMenu.getUrl());
                    }
                }
            }
        }
        log.debug("-------通过数据库读取用户拥有的权限Perms------username： {}, Perms size: {}", userId, (permissionSet == null ? 0 : permissionSet.size()));
        return permissionSet;
    }

    /**
     * 根据手机号查询用户信息
     *
     * @param phone - 手机号
     * @return SysUser - 用户信息
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/21 16:00
     */
    @Override
    public SysUser queryUserByPhone(final String phone) {
        return mapper.queryUserByPhone(phone);
    }

    /**
     * 根据邮箱查询用户信息
     *
     * @param email - 邮箱
     * @return SysUser - 用户信息
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/21 16:00
     */
    @Override
    public SysUser queryUserByEmail(final String email) {
        return mapper.queryUserByEmail(email);
    }

    /**
     * 修改密码
     *
     * @param username    - 用户名
     * @param newPassword - 新密码
     * @return Boolean - 成功标志
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/12 17:25
     */
    @Override
    public Boolean changeUserPassword(final String username, final String newPassword) {
        // 取盐
        String stringSalt = PasswordUtil.getStringSalt();
        // 更新
        int changeUserPassword = mapper.changeUserPassword(username, PasswordUtil.encrypt(username, newPassword, stringSalt), stringSalt);
        return changeUserPassword > 0;
    }

}
